﻿using System;
using System.Collections.Generic;
using System.Windows.Media.Media3D;
using LFSRecord2.Model.Replay;
using LFSRecord2.Model.Media;
using LFSRecord2.Misc;

namespace LFSRecord2.Model
{
    public class CompLayerReplayData : CompLayerBase
    {
        public enum PropertyTypes
        {
            DataSelection = 0,
            TimeOffset = 1,
            Position = 2,
            Heading = 3,
        }

        [Flags]
        public enum PropertyTypesFlags
        {
            None = 0,
            DataSelection = 1,
            TimeOffset = 2,
            Position = 4,
            Heading = 8,
        }

        public CompLayerReplayData(short layerIndex, string layerName)
        {
            UniqueID = MathHelper.UniqueID;
            LayerIndex = layerIndex;
            LayerType = CompLayerTypes.ReplayData;
            LayerName = layerName;
            LayerObjectMesh = new CompLayerReplayDataMesh();

            // Setup properties
            Properties = new List<CompLayerPropertyBase>(4);
            Properties.Add(new CompLayerPropertyRDIdent(this, 0, "Data Source", new RDIdent(), LayerPropertyValueMeaning.Generic));
            Properties.Add(new CompLayerPropertyDouble(this, 1, "Time Offset", 0, LayerPropertyValueMeaning.Timestamp));
            Properties.Add(new CompLayerPropertyPoint3DRD(this, 2, "Position", new Point3D(0, 0, 0), LayerPropertyValueMeaning.Generic));
            Properties.Add(new CompLayerPropertyDoubleRD(this, 3, "Heading", 0, LayerPropertyValueMeaning.Degrees));

            ((CompLayerPropertyDouble)Properties[(int)PropertyTypes.TimeOffset]).MinValue = 0;
            
            SetCurrentTransformMatrix();
        }

        public override Matrix3D GetTransformMatrixAtFrame(int frame)
        {
            Matrix3D mTr = new Matrix3D();

            // Heading
            mTr.Rotate(new Quaternion(new Vector3D(0, 0, 1), (double)((CompLayerPropertyDoubleRD)Properties[(int)PropertyTypes.Heading]).GetValueAtFrame(frame)));

            // Translate the matrix
            Point3D pos = (Point3D)((CompLayerPropertyPoint3DRD)Properties[(int)PropertyTypes.Position]).GetValueAtFrame(frame);
            mTr.Translate(new Vector3D(pos.X, pos.Y, pos.Z));

            return mTr;
        }

        public override void SetMeshLookAtPointAtFrame(int frame)
        {
        }

        public override void SetMeshCenterPointAtFrame(int frame)
        {
        }

        public override void RemoveParentingJump(CompLayerBase parentLayer)
        {
        }

        public override void AddParentingJump()
        {
        }

        public ReplayPlayerData CurrentReplayPlayerData(int frame)
        {
            RDIdent ri = (RDIdent)Properties[(int)PropertyTypes.DataSelection].GetValueAtFrame(frame);
            int mediaIndex = LfsRecordController.project.HasMediaFile(ri.ReplayFilePath);
            if (mediaIndex == -1 || LfsRecordController.project.MediaObjects[mediaIndex].MediaType != MediaTypes.ReplayData)
                return null;

            MediaReplayData mrd = (MediaReplayData)LfsRecordController.project.MediaObjects[mediaIndex];
            if (mrd.FileStatus != MediaFileStatus.Loaded)
                return null;

            ReplayPlayerData rpd = mrd.RData.GetPlayerByIndex(ri.PlayerIndex);
            if (rpd.PlayerName != ri.PlayerName)
            {
                int i = mrd.RData.GetPlayerIndexByName(ri.PlayerName);
                if (i > -1)
                {
                    ri.PlayerIndex = i;
                    return mrd.RData.GetPlayerByIndex(ri.PlayerIndex);
                }

                return null;
            }

            return rpd;
        }

        public double CurrentReplayTimeOffset(int frame)
        {
            return (double)Properties[(int)PropertyTypes.TimeOffset].GetValueAtFrame(frame);
        }

        public RDIdent FirstRDIdent()
        {
            if (Properties[(int)PropertyTypes.DataSelection].KeyFrames.Count == 0)
            {
                // Return currentvalue
                return ((CompLayerPropertyRDIdent)Properties[(int)PropertyTypes.DataSelection]).CurrentValue;
            }
            else
            {
                // return first keyframe's value
                return ((CustomRDKeyFrame)Properties[(int)PropertyTypes.DataSelection].KeyFrames[0]).Value;
            }
        }
    }
}
